package com.gitee.faster.webdav.kernel;

import cn.hutool.core.util.RuntimeUtil;
import com.gitee.faster.webdav.common.Server;
import com.gitee.faster.webdav.exception.WebDavException;
import com.gitee.faster.webdav.kernel.event.EventPublisher;
import com.gitee.faster.webdav.kernel.event.PreparedHomeEvent;
import com.gitee.faster.webdav.kernel.plugin.DataRateMonitorPlugin;
import com.gitee.faster.webdav.kernel.protocol.HttpDispatcherHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.smartboot.http.server.HttpBootstrap;

/**
 * @author hongda.li
 */
public class FasterWebDavServer implements Server {
    /**
     * HTTP 服务器
     */
    private final HttpBootstrap bootstrap;

    /**
     * 全局配置
     */
    private final Configuration configuration = Configuration.getInstance();

    /**
     * 初始化 SLF4J 日志
     * 此处不能使用 @Lombok，保证 logger 在 configuration 后实例化
     */
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 事件发布器
     */
    private final EventPublisher eventPublisher = EventPublisher.getInstance();

    public FasterWebDavServer() {
        this.configuration.rewriteFromJson();
        this.bootstrap = new HttpBootstrap();
        this.bootstrap.httpHandler(new HttpDispatcherHandler());
        this.bootstrap.setPort(this.configuration.getPort());
        this.bootstrap.configuration()
                // 禁用低内存模式
                .setLowMemory(false)
                // 禁用Banner
                .bannerEnabled(false)
                // 读缓冲区大小
                .readBufferSize(this.configuration.getReadBufferSize())
                // 写缓冲区大小
                .writeBufferSize(this.configuration.getWriteBufferSize())
                // 主机地址
                .host(this.configuration.withReplacedHost())
                // 服务端名称
                .serverName(this.getClass().getSimpleName())
                // 线程数
                .threadNum(Math.max(RuntimeUtil.getProcessorCount(), 4))
                // 码流速率监控
                .addPlugin(new DataRateMonitorPlugin());
    }

    @Override
    public void start() {
        // 关闭虚拟机前停止当前服务
        RuntimeUtil.addShutdownHook(this::shutdown);

        // 发送服务启动前事件
        PreparedHomeEvent preparedHomeEvent = new PreparedHomeEvent(this);
        this.eventPublisher.publishEvent(preparedHomeEvent);

        try {
            // 启动HTTP服务器
            this.bootstrap.start();
        } catch (Exception e) {
            logger.error("WebDav服务启动失败", e);
            throw new WebDavException(e);
        }

        this.configuration.show(logger);
    }

    @Override
    public void shutdown() {
        // 关闭服务器并释放资源
        this.bootstrap.shutdown();
        logger.info("WebDav服务成功关闭");
    }
}
